/******************************************************************************
*
*    File Name:  DDRTESTBENCH.V
*      Version:  1.0
*         Date:  June 13th, 2013
*        Model:  
*    Simulator:  Questa Sim- Mentor Graphics (Version 64 10.2a)
*
* Dependencies:  DDRInterface.sv, DDRStub.sv
*
*       Author:  Nachiket Khasbag & Nikhil Patil 
*        Email:  nachiket@pdx.edu, pnikhil@gmail.com
*        Phone:  404-660-0757, 971-300-1728
*   University:  Portland State University
*
*  Description:  This is a testbench for DDRInterface.sv
*
*
******************************************************************************/

`timescale 1ns / 1ps
import DDRStub::*;
module test;

reg                             clk;
logic        [BUFFER_WIDTH-1:0] BUFFER;
reg                             dqs;
logic        [DATA_WIDTH-1:0]   dq;
int                             cnt = 0;

parameter            half_clk   =  5;
parameter            full_clk   = 10;

int refresh_counter = 0;

// Instantiate modules in testbench
DDRInterface DDR3        (.clk(clk));
testcase     testcase    (.clk(clk));


// GENERATE CLOCK
initial 
begin
  clk               =   1'b0;
end

initial 
begin
  forever #half_clk clk = ~clk;
end


always@(posedge clk)
begin
if(refresh_counter == 10000)
  begin
    DDR3.refresh;
    refresh_counter = 0;
  end
end


// DEFINE CLASS FOR RANDOM ADDRESS GENERATION
class ver;
  rand int row,col;
  rand bit bank;
  constraint c1{ row > 0;
                 row < 127;
                 col > 50;
                 col < 100;}
endclass

ver v;



task automatic nop;
  input  [3:0]             delay;
  
  begin
    DDR3.nop(delay);
  end
endtask

task automatic activate;
  input          bank;
  input  [ROW_LINES-1 : 0] row;
  begin
    DDR3.activate(bank,row);
  end
endtask


task automatic precharge;
  input          bank;
  begin
    DDR3.precharge(bank);
  end
endtask

task automatic write;
  input  [COL_LINES-1 : 0] col;
  
  begin
    DDR3.write(col);
    @(DDR3.poscb)
    DDR3.poscb.write_data   <= 1'b1;
    for(cnt = 0; cnt < BURST_LENGTH/2; cnt++) 
    begin   
      DDR3.poscb.dq         <= $random;
      @(DDR3.negcb)  
      DDR3.negcb.dq         <= $random;      
    end
    @(DDR3.poscb)
    DDR3.poscb.write_data   <= 1'b0;
   
    
  end
endtask

task automatic read;
  input  [COL_LINES-1 : 0] col;
  
  begin
    DDR3.read(col);
    
    for(cnt = 0; cnt < (BURST_LENGTH); cnt++) 
    begin
      @(DDR3.dqs)
      BUFFER = BUFFER<<DATA_WIDTH;
      BUFFER[DATA_WIDTH-1:0]       = DDR3.dq;    
    end
  end
endtask
  
endmodule
